#ifndef TORRENTCONNECTION_H
#define TORRENTCONNECTION_H

#include <QTcpSocket>
#include "torrentpeerdata.h"

class TorrentPeerObserver;

class QTimer;

/*
 * class representing a connection with single Torrent peer
 */
class TorrentConnection : public QObject
{

    Q_OBJECT

public:
    TorrentConnection(TorrentPeerData data, TorrentPeerObserver& obs, QObject* parent = 0);
    ~TorrentConnection();
    void init(const QByteArray& aInfoHash);
    void stop();
    void setPeerInteresting(bool isInteresting);
    bool hasPiece(int pieceIndex);
    void sendRequestPiece(int pieceIndex, int begin, int length);
    void cancelPiece(int pieceIndex, int begin, int length);
    const TorrentPeerData& getPeerData();
    static quint32 convertFromBigEndian(QByteArray& data);
    static QByteArray convertFromLittleEndian(quint32 littleEndianInt);
private:
    void sendHandshake();
    void receiveHandshake(QByteArray& dataReceived);
    void receiveChoke();
    void receiveUnchoke();
    void receiveInterested();
    void receiveNotInterested();
    void receiveHave(const QByteArray& data);
    void receiveBitfield(const QByteArray& data);
    void receiveRequest(const QByteArray& data);
    void receivePiece(const QByteArray& data);
    void receiveCancel(const QByteArray& data);
    void dispatchMessage(QByteArray& dataRead);

    void checkError(int errorCode);
private slots:
    void connectedToPeer();
    void peerDisconnected();
    void dataReceived();
    void sendKeepAlive();
    void timedOut();
private: //data

    enum TorrentConnectionState
    {
      NotConnected,
      WaitingForHandshake,
      HandshakeReceived
    };

    enum TorrentMessageId
    {
        Choke = 0,
        Unchoke = 1,
        Interested = 2,
        NotInterested = 3,
        Have = 4,
        Bitfield = 5,
        Request = 6,
        Piece = 7,
        Cancel = 8
        //some other message types are optional (protocol extensions)
    };

    TorrentPeerData peerData;
        TorrentPeerObserver& peerObserver;
    TorrentConnectionState connectionState;

    QTcpSocket* socket;
    QByteArray infoHash;
    QByteArray* readBuffer;
    QByteArray* pieceDownloaded;
    QTimer* timerKeepAliveSending;
    QTimer* timerKeepAliveReceiving;
    QTimer* timerPieceDownloading;
    int dataAmountToReceive;
};

#endif // TORRENTCONNECTION_H
